package com.ruoyi.AliYunOss;
/**
 * @Description:
 * @Author: 吕宇宏
 * @Date: 2024/7/9 16:47
 */

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.utils.HttpHeaders;
import com.aliyun.oss.model.OSSObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.Config.TemplateFileProperties;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.order.domain.SysOrderOne;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private  String accessKeySecret;
    private  String bucketName;


    /**
     * 文件上传
     *
     * @param
     * @param objectName
     * @return
     */
    public String upload(FileInputStream fileInputStream, String objectName) {



        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, fileInputStream);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());

        return stringBuilder.toString();
    }


    public ResponseEntity<Object> download(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        OSSObject ossObject = ossClient.getObject(bucketName,fileName);
        BufferedInputStream inputStream = new BufferedInputStream(ossObject.getObjectContent());

        // 设置响应头
        String contentType = ossObject.getObjectMetadata().getContentType();
        if (contentType == null) {
            // 如果没有设置ContentType，则默认为application/octet-stream（二进制流）
            contentType = "application/octet-stream";
        }
        String fileNameToDownload = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        // 注意：这里为了兼容旧版浏览器，将文件名编码为ISO-8859-1
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileNameToDownload + "\"");

        // 但由于我们使用的是ResponseEntity，这里实际上不会设置到HttpServletResponse中
        // 相反，我们将InputStream封装成InputStreamResource并返回
        InputStreamResource resource = new InputStreamResource(inputStream);

        // 返回ResponseEntity，包含文件内容、文件类型和其他HTTP头
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileNameToDownload + "\"")
                .body(resource);

    }



    public static String downloadFile(String fileUrl, String localFilePath) {
        try {
            URL url = new URL(fileUrl);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

            // 设置请求方法
            httpURLConnection.setRequestMethod("GET");

            // 连接（不读取响应体）
            int responseCode = httpURLConnection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 获取输入流
                InputStream inputStream = httpURLConnection.getInputStream();

                // 创建文件输出流
                FileOutputStream fileOutputStream = new FileOutputStream(localFilePath);

                // 缓冲区
                byte[] buffer = new byte[4096];
                int bytesRead;

                // 读取输入流并写入到文件输出流
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, bytesRead);
                }

                // 关闭流
                fileOutputStream.close();
                inputStream.close();

                // 关闭连接
                httpURLConnection.disconnect();

                System.out.println("文件下载成功：" + localFilePath);
                return localFilePath;
            } else {
                System.out.println("无法下载文件，HTTP响应码：" + responseCode);
                throw new ServiceException("文件下载失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public void createZipAndSend(HttpServletResponse response, List<String> fileUrls, SysOrderOne orderOne) {
        OutputStream outputStream = null;
        response.setContentType("application/zip");
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ZipOutputStream zos = new ZipOutputStream(outputStream);
        AtomicInteger atomicInteger = new AtomicInteger(0);
        for (String fileUrl : fileUrls) {
            // 假设你已经有了一个方法downloadFileToTemp(fileUrl)来下载文件到临时位置
            //todo 临时位置
            String localFilePath  = "D:/docHtml"+orderOne.getNumber()+orderOne.getCdName()+atomicInteger.incrementAndGet()+".pdf";

            File tempFile = new File(downloadFile(fileUrl,localFilePath));
            ZipEntry zipEntry = new ZipEntry(tempFile.getName());
            FileInputStream fis=null;
            try {
                zos.putNextEntry(zipEntry);

                 fis = new FileInputStream(tempFile);
                byte[] buffer = new byte[1024];
                int length;
                while ((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    zos.closeEntry();
                    fis.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
                // 清理临时文件
                tempFile.delete();
            }

        }
        try {
            zos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }


    public void createZipAndSendMore(HttpServletResponse response, Map<Long,List<String>> urlMap,Map<Long,SysOrderOne> orderMap) {
        OutputStream outputStream = null;
        response.setContentType("application/zip");
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ZipOutputStream zos = new ZipOutputStream(outputStream);




        urlMap.keySet().stream().forEach(key -> {
            AtomicInteger atomicInteger = new AtomicInteger(0);
            List<String> fileUrls = urlMap.get(key);
            SysOrderOne orderOne = orderMap.get(key);
            if (!CollectionUtils.isEmpty(fileUrls)) {
                for (String fileUrl : fileUrls) {
                    // 假设你已经有了一个方法downloadFileToTemp(fileUrl)来下载文件到临时位置
                    //todo 临时位置

                    String localFilePath = "D:/docHtml"+orderOne.getNumber()+orderOne.getCdName() + atomicInteger.incrementAndGet() + ".pdf";

                    File tempFile = new File(downloadFile(fileUrl, localFilePath));
                    ZipEntry zipEntry = new ZipEntry(tempFile.getName());
                    FileInputStream fis = null;
                    try {
                        zos.putNextEntry(zipEntry);

                        fis = new FileInputStream(tempFile);
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = fis.read(buffer)) > 0) {
                            zos.write(buffer, 0, length);
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            zos.closeEntry();
                            fis.close();

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        // 清理临时文件
                        tempFile.delete();
                    }

                }
            }
        });

        try {
            zos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

